home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
AMIGA-CD 2
/
Amiga-CD - Volume 2.iso
/
gepackte_disketten
/
1994
/
08_94_5.dms
/
08_94_5.adf
/
term-4.0-Source.lha
/
termBuffer.c
< prev
next >
Wrap
C/C++ Source or Header
|
1994-06-27
|
21KB
|
1,092 lines
/*
** termBuffer.c
**
** Auxilary routines for text buffer/capture management.
**
** Copyright © 1990-1994 by Olaf `Olsen' Barthel
** All Rights Reserved
*/
#include "termGlobal.h"
/* Search string window gadgets. */
enum { GAD_STRING,GAD_FORWARD,GAD_OK,GAD_CANCEL };
/* Maximum size of an allocated line string. */
#define STRING_SIZE (1 + 255 + 1)
/* How many strings to include in a single puddle. */
#define STRING_COUNT 10
/* The number of lines the buffer will grow. */
#define BUFFER_GROW 100
/* Memory pool header. */
STATIC APTR BufferPoolHeader;
/* AllocString(STRPTR String,WORD Len):
*
+ Allocate space for a string, new pooled version.
*/
STATIC STRPTR __regargs
AllocString(STRPTR String,LONG Len)
{
STRPTR Mem;
if(Len > 255)
Len = 255;
if(Mem = (STRPTR)LibAllocPooled(BufferPoolHeader,1 + Len + 1))
{
*Mem++ = Len;
CopyMem(String,Mem,Len);
Mem[Len] = 0;
return((STRPTR)Mem);
}
else
return(NULL);
}
/* FreeString(STRPTR String):
*
* Free the space occupied by a string, new pooled version.
*/
STATIC VOID __regargs
FreeString(STRPTR String)
{
LibFreePooled(BufferPoolHeader,&String[-1],1 + String[-1] + 1);
}
/* AddLine(STRPTR Line,LONG Size):
*
* Add a line to the display buffer.
*/
STATIC VOID __regargs
AddLine(register STRPTR Line,register LONG Size)
{
/* Are we still to update the buffer contents? */
if(!BufferClosed)
{
/* Remove trailing spaces. */
/*
while(Size > 0 && Line[Size - 1] == ' ')
Size--;
*/
/* Is the buffer array initialized? */
if(BufferLines)
{
ULONG Signals = 0;
/* Pick up the global access semaphore
* (two tasks are sharing the data).
*/
ObtainSemaphore(BufferSemaphore);
/* Check for limit. */
if(Config -> CaptureConfig -> MaxBufferSize && BufferSpace >= Config -> CaptureConfig -> MaxBufferSize)
{
register LONG i;
BufferSpace -= BufferLines[0][-1];
FreeString(BufferLines[0]);
for(i = 1 ; i < MaxLines ; i++)
BufferLines[i - 1] = BufferLines[i];
Lines--;
/* Tell the buffer task to
* refresh the display.
*/
Signals = SIG_MOVEUP;
}
else
{
/* We've reached the last line in the buffer. */
if(Lines == MaxLines)
{
STRPTR *MoreBuffer;
/* Allocate space for some more lines. */
if(MoreBuffer = (STRPTR *)AllocVecPooled((MaxLines + BUFFER_GROW) * sizeof(STRPTR),MEMF_ANY | MEMF_CLEAR))
{
register LONG i;
BufferChanged = TRUE;
/* Copy the old lines to the new
* buffer.
*/
for(i = 0 ; i < Lines ; i++)
MoreBuffer[i] = BufferLines[i];
/* Free the old lines. */
FreeVecPooled(BufferLines);
/* Set the new buffer. */
MaxLines += BUFFER_GROW;
BufferLines = MoreBuffer;
}
else
{
BufferChanged = TRUE;
/* We couldn't get enough memory
* to extend the number of lines
* in the buffer, so we'll have
* to wrap the contents of the
* buffer around.
*/
if(Lines)
{
register LONG i;
BufferSpace -= BufferLines[0][-1];
FreeString(BufferLines[0]);
for(i = 1 ; i < MaxLines ; i++)
BufferLines[i - 1] = BufferLines[i];
Lines--;
/* Tell the buffer task to
* refresh the display.
*/
Signals = SIG_MOVEUP;
}
}
}
}
/* Allocate a new line and copy the buffer contents
* into it.
*/
if(BufferLines[Lines] = AllocString(Line,Size))
{
BufferChanged = TRUE;
Lines++;
BufferSpace += Size;
}
ReleaseSemaphore(BufferSemaphore);
/* Tell the buffer task to update the display. */
if(!Signals)
{
Signals = SIG_UPDATE;
UpdateReview(FALSE);
}
else
UpdateReview(TRUE);
ObtainSemaphore(&BufferTaskSemaphore);
if(BufferTask && Signals)
{
Forbid();
ClrSignal(SIG_HANDSHAKE);
Signal(BufferTask,Signals);
Wait(SIG_HANDSHAKE);
Permit();
}
ReleaseSemaphore(&BufferTaskSemaphore);
}
}
}
/* StoreBuffer(APTR Buffer,LONG Size):
*
* Store data in the display buffer.
*/
VOID __regargs
StoreBuffer(register STRPTR Buffer,register LONG Size)
{
STATIC UBYTE __far LineBuffer[BUFFER_LINE_MAX + 1];
STATIC LONG BufferCount = 0;
register UBYTE c;
while(Size--)
{
/* Look which char we are to handle. */
switch(c = *Buffer++)
{
/* Move the cursor one step back. */
case BKS:
if(BufferCount)
BufferCount--;
break;
/* Move the cursor to the next tab
* stop.
*/
case TAB:
if(((BufferCount + 8) & ~7) < LastColumn)
{
register LONG Delta = ((BufferCount + 8) & ~7) - BufferCount;
memset(&LineBuffer[BufferCount],' ',Delta);
BufferCount += Delta;
}
else
{
AddLine(LineBuffer,BufferCount);
BufferCount = 0;
}
break;
/* Terminate the current line. */
case ENT:
AddLine(LineBuffer,BufferCount);
BufferCount = 0;
break;
/* Stuff the character into the buffer. */
default:
if(Config -> TerminalConfig -> FontMode == FONT_STANDARD)
{
if(IsPrintable[c])
LineBuffer[BufferCount++] = c;
}
else
{
if(c)
LineBuffer[BufferCount++] = c;
}
break;
}
/* The line is full, add it to the display buffer. */
if(BufferCount >= LastColumn || BufferCount == Config -> CaptureConfig -> BufferWidth)
{
AddLine(LineBuffer,BufferCount);
BufferCount = 0;
}
}
}
/* DeleteBuffer():
*
* Delete buffer resources.
*/
VOID
DeleteBuffer()
{
if(BufferLines)
{
FreeVecPooled(BufferLines);
BufferLines = NULL;
}
if(BufferPoolHeader)
{
LibDeletePool(BufferPoolHeader);
BufferPoolHeader = NULL;
}
if(BufferSemaphore)
{
FreeVecPooled(BufferSemaphore);
BufferSemaphore = NULL;
}
}
/* CreateBuffer():
*
* Allocate buffer resources.
*/
BYTE
CreateBuffer()
{
if(BufferLines = (STRPTR *)AllocVecPooled(MaxLines * sizeof(STRPTR),MEMF_ANY | MEMF_CLEAR | MEMF_PUBLIC))
{
if(BufferSemaphore = (struct SignalSemaphore *)AllocVecPooled(sizeof(struct SignalSemaphore),MEMF_ANY | MEMF_PUBLIC))
{
InitSemaphore(BufferSemaphore);
/* Create a memory pool header if possible. */
if(BufferPoolHeader = LibCreatePool(MEMF_ANY | MEMF_PUBLIC,STRING_SIZE * STRING_COUNT,STRING_SIZE * STRING_COUNT))
return(TRUE);
}
FreeVecPooled(BufferLines);
BufferLines = NULL;
}
return(FALSE);
}
/* FreeBuffer():
*
* Release the contents of the text buffer.
*/
VOID
FreeBuffer()
{
/* Free the contents of the display buffer. */
if(BufferLines)
{
APTR NewPoolHeader;
/* If a new pool header is available, free the old
* pool and replace it with the new pool.
*/
if(NewPoolHeader = LibCreatePool(MEMF_ANY | MEMF_PUBLIC,STRING_SIZE * STRING_COUNT,STRING_SIZE * STRING_COUNT))
{
LibDeletePool(BufferPoolHeader);
BufferPoolHeader = NewPoolHeader;
}
else
{
LONG i;
for(i = 0 ; i < Lines ; i++)
{
if(BufferLines[i])
FreeString(BufferLines[i]);
}
}
FreeVecPooled(BufferLines);
Lines = 0;
MaxLines = BUFFER_GROW;
BufferLines = (STRPTR *)AllocVecPooled(MaxLines * sizeof(STRPTR),MEMF_ANY | MEMF_CLEAR);
UpdateReview(TRUE);
}
BufferSpace = 0;
BufferChanged = FALSE;
}
/* DeleteSearchInfo(struct SearchInfo *Info):
*
* Free buffer allocated by CreateSearchInfo().
*/
VOID __regargs
DeleteSearchInfo(struct SearchInfo *Info)
{
if(Info)
FreeVecPooled(Info);
}
/* CreateSearchInfo(STRPTR Pattern):
*
* Create auxilary data required by SearchTextBuffer().
*/
struct SearchInfo * __regargs
CreateSearchInfo(STRPTR Pattern,BOOLEAN Forward,BOOLEAN IgnoreCase)
{
struct SearchInfo *Info;
/* Allocate the buffer. */
if(Info = (struct SearchInfo *)AllocVecPooled(sizeof(struct SearchInfo),MEMF_ANY | MEMF_PUBLIC))
{
WORD i;
/* Determine pattern width. */
Info -> PatternWidth = strlen(Pattern);
Info -> IgnoreCase = IgnoreCase;
/* Turn the pattern into upper case characters. */
if(IgnoreCase)
{
for(i = 0 ; i <= Info -> PatternWidth ; i++)
Info -> Pattern[i] = ToUpper(Pattern[i]);
}
else
{
for(i = 0 ; i <= Info -> PatternWidth ; i++)
Info -> Pattern[i] = Pattern[i];
}
/* Fill the entire range with the maximum pattern width. */
for(i = 0 ; i < 256 ; i++)
Info -> Distance[i] = Info -> PatternWidth;
/* Fill in the matching distances. */
if(Forward)
{
for(i = 0 ; i < Info -> PatternWidth - 1 ; i++)
Info -> Distance[Info -> Pattern[i]] = Info -> PatternWidth - 1 - i;
}
else
{
for(i = Info -> PatternWidth - 1 ; i > 0 ; i--)
Info -> Distance[Info -> Pattern[i]] = i;
}
/* Restart from scratch. */
Info -> FoundY = -1;
Info -> Forward = Forward;
}
return(Info);
}
/* SearchTextBuffer():
*
* String search function, based on the Boyer-Moore search
* algorithm.
*/
LONG __regargs
SearchTextBuffer(struct SearchInfo *Info)
{
if(BufferLines)
{
UBYTE *Distance,
*Pattern;
WORD LineWidth,
PatternWidth;
STRPTR Line;
LONG i;
WORD SearchPosition,PatternIndex,LineIndex,LastSearchPosition;
/* Extract the relevant data. */
Distance = Info -> Distance;
Pattern = Info -> Pattern;
PatternWidth = Info -> PatternWidth;
/* Which direction are we to search? */
if(Info -> IgnoreCase)
{
if(Info -> Forward)
{
/* Update the search positions. */
if(Info -> FoundY == -1)
{
Info -> FoundX = 0;
Info -> FoundY = 0;
LastSearchPosition = 0;
}
else
{
/* Proceed to the next line. */
if(!(LastSearchPosition = Info -> Index))
Info -> FoundY = (Info -> FoundY + 1) % Lines;
}
/* Run down the buffer. */
for(i = Info -> FoundY ; i < Lines ; i++)
{
Line = BufferLines[i];
/* Is there anything to search for? */
if((LineWidth = Line[-1]) >= PatternWidth)
{
/* Where are we to start searching? */
if(LastSearchPosition)
SearchPosition = LastSearchPosition;
else
SearchPosition = PatternWidth;
do
{
/* How many line characters
* match the pattern?
*/
PatternIndex = PatternWidth - 1;
LineIndex = SearchPosition - 1;
while(PatternIndex >= 0 && Pattern[PatternIndex] == ToUpper(Line[LineIndex]))
{
LineIndex--;
PatternIndex--;
}
/* Update the line search index
* for subsequent searches.
*/
SearchPosition += Distance[ToUpper(Line[SearchPosition - 1])];
/* Found the pattern? */
if(PatternIndex < 0)
{
/* Store the position. */
Info -> FoundX = LineIndex + 1;
Info -> FoundY = i;
/* Remember column to start
* next search attempt at.
*/
if(SearchPosition <= LineWidth)
Info -> Index = SearchPosition;
else
Info -> Index = 0;
return(i);
}
}
while(SearchPosition <= LineWidth);
}
/* Reset search column. */
LastSearchPosition = 0;
}
}
else
{
/* Update the search positions. */
if(Info -> FoundY == -1)
{
Info -> FoundX = 0;
Info -> FoundY = Lines - 1;
LastSearchPosition = 0;
}
else
{
if((LastSearchPosition = Info -> Index) < 1)
{
if(Info -> FoundY)
Info -> FoundY--;
else
Info -> FoundY = Lines - 1;
}
}
/* Run down the buffer. */
for(i = Info -> FoundY ; i >= 0 ; i--)
{
Line = BufferLines[i];
/* Is there anything to search for? */
if((LineWidth = Line[-1]) >= PatternWidth)
{
/* Cast the magic spell of Boyer-Moore... */
if(LastSearchPosition < 1)
SearchPosition = LineWidth - (PatternWidth - 1);
else
SearchPosition = LastSearchPosition;
do
{
PatternIndex = 0;
LineIndex = SearchPosition - 1;
while(PatternIndex < PatternWidth && Pattern[PatternIndex] == ToUpper(Line[LineIndex]))
{
LineIndex++;
PatternIndex++;
}
SearchPosition -= Distance[ToUpper(Line[SearchPosition - 1])];
if(PatternIndex == PatternWidth)
{
Info -> FoundX = LineIndex - PatternWidth;
Info -> FoundY = i;
Info -> Index = SearchPosition;
return(i);
}
}
while(SearchPosition > 0);
}
LastSearchPosition = 0;
}
}
}
else
{
if(Info -> Forward)
{
/* Update the search positions. */
if(Info -> FoundY == -1)
{
Info -> FoundX = 0;
Info -> FoundY = 0;
LastSearchPosition = 0;
}
else
{
/* Proceed to the next line. */
if(!(LastSearchPosition = Info -> Index))
Info -> FoundY = (Info -> FoundY + 1) % Lines;
}
/* Run down the buffer. */
for(i = Info -> FoundY ; i < Lines ; i++)
{
Line = BufferLines[i];
/* Is there anything to search for? */
if((LineWidth = Line[-1]) >= PatternWidth)
{
/* Where are we to start searching? */
if(LastSearchPosition)
SearchPosition = LastSearchPosition;
else
SearchPosition = PatternWidth;
do
{
/* How many line characters
* match the pattern?
*/
PatternIndex = PatternWidth - 1;
LineIndex = SearchPosition - 1;
while(PatternIndex >= 0 && Pattern[PatternIndex] == Line[LineIndex])
{
LineIndex--;
PatternIndex--;
}
/* Update the line search index
* for subsequent searches.
*/
SearchPosition += Distance[Line[SearchPosition - 1]];
/* Found the pattern? */
if(PatternIndex < 0)
{
/* Store the position. */
Info -> FoundX = LineIndex + 1;
Info -> FoundY = i;
/* Remember column to start
* next search attempt at.
*/
if(SearchPosition <= LineWidth)
Info -> Index = SearchPosition;
else
Info -> Index = 0;
return(i);
}
}
while(SearchPosition <= LineWidth);
}
/* Reset search column. */
LastSearchPosition = 0;
}
}
else
{
/* Update the search positions. */
if(Info -> FoundY == -1)
{
Info -> FoundX = 0;
Info -> FoundY = Lines - 1;
LastSearchPosition = 0;
}
else
{
if((LastSearchPosition = Info -> Index) < 1)
{
if(Info -> FoundY)
Info -> FoundY--;
else
Info -> FoundY = Lines - 1;
}
}
/* Run down the buffer. */
for(i = Info -> FoundY ; i >= 0 ; i--)
{
Line = BufferLines[i];
/* Is there anything to search for? */
if((LineWidth = Line[-1]) >= PatternWidth)
{
/* Cast the magic spell of Boyer-Moore... */
if(LastSearchPosition < 1)
SearchPosition = LineWidth - (PatternWidth - 1);
else
SearchPosition = LastSearchPosition;
do
{
PatternIndex = 0;
LineIndex = SearchPosition - 1;
while(PatternIndex < PatternWidth && Pattern[PatternIndex] == Line[LineIndex])
{
LineIndex++;
PatternIndex++;
}
SearchPosition -= Distance[Line[SearchPosition - 1]];
if(PatternIndex == PatternWidth)
{
Info -> FoundX = LineIndex - PatternWidth;
Info -> FoundY = i;
Info -> Index = SearchPosition;
return(i);
}
}
while(SearchPosition > 0);
}
LastSearchPosition = 0;
}
}
}
}
return(-1);
}
STATIC ULONG __asm __saveds
HistoryFunc(register __a0 struct Hook *Hook,register __a1 STRPTR NewString)
{
struct List *List = (struct List *)Hook -> h_Data;
if(NewString)
{
struct Node *Node = CreateNode(NewString);
if(Node)
AddTail(List,Node);
else
return(FALSE);
}
else
{
struct Node *Node = RemHead(List);
FreeNode(Node);
}
return(TRUE);
}
/* GetSearchString():
*
* Prompt the user for a search string.
*/
BYTE __regargs
GetSearchString(struct Window *ParentWindow,BYTE *ParentTerminated,STRPTR Buffer,struct Hook *HistoryHook,BYTE *Forward,BYTE *IgnoreCase)
{
enum { GAD_OK=1,GAD_CANCEL,GAD_STRING };
struct LayoutHandle *Handle;
BYTE Success = FALSE;
if(HistoryHook)
HistoryHook -> h_Entry = (HOOKFUNC)HistoryFunc;
if(Handle = LT_CreateHandleTags(ParentWindow -> WScreen,
LH_LocaleHook, &LocaleHook,
TAG_DONE))
{
UBYTE LocalBuffer[256];
struct Window *Window;
LocalBuffer[0] = 0;
LT_New(Handle,
LA_Type, VERTICAL_KIND,
TAG_DONE);
{
LT_New(Handle,
LA_Type, HORIZONTAL_KIND,
LA_LabelText, LocaleString(MSG_TERMBUFFER_ENTER_SEARCH_STRING_TXT),
TAG_DONE);
{
LT_New(Handle,
LA_Type, VERTICAL_KIND,
TAG_DONE);
{
LT_New(Handle,
LA_Type, STRING_KIND,
LA_LabelID, MSG_V36_0788,
LA_STRPTR, LocalBuffer,
LA_Chars, 30,
LA_ID, GAD_STRING,
LAST_HistoryLines, MAX(Config -> CaptureConfig -> SearchHistory,1),
LAST_HistoryHook, HistoryHook,
GTST_MaxChars, 255,
TAG_DONE);
LT_EndGroup(Handle);
}
LT_New(Handle,
LA_Type, VERTICAL_KIND,
TAG_DONE);
{
LT_New(Handle,
LA_Type, CHECKBOX_KIND,
LA_LabelID, MSG_TERMBUFFER_SEARCH_FORWARD_TXT,
LA_BYTE, Forward,
TAG_DONE);
LT_New(Handle,
LA_Type, CHECKBOX_KIND,
LA_LabelID, MSG_TEXTBUFFER_IGNORE_CASE_GAD,
LA_BYTE, IgnoreCase,
TAG_DONE);
LT_EndGroup(Handle);
}
LT_EndGroup(Handle);
}
LT_New(Handle,
LA_Type, VERTICAL_KIND,
TAG_DONE);
{
LT_New(Handle,LA_Type,XBAR_KIND,LAXB_FullSize,TRUE,TAG_DONE);
LT_EndGroup(Handle);
}
LT_New(Handle,LA_Type,HORIZONTAL_KIND,
LAGR_SameSize, TRUE,
LAGR_Spread, TRUE,
TAG_DONE);
{
LT_New(Handle,
LA_Type, BUTTON_KIND,
LA_LabelID, MSG_TERMXPR_OKAY_GAD,
LA_ID, GAD_OK,
LABT_ReturnKey, TRUE,
LABT_ExtraFat, TRUE,
TAG_DONE);
LT_New(Handle,
LA_Type, BUTTON_KIND,
LA_LabelID, MSG_GLOBAL_CANCEL_GAD,
LA_ID, GAD_CANCEL,
LABT_EscKey, TRUE,
LABT_ExtraFat, TRUE,
TAG_DONE);
LT_EndGroup(Handle);
}
LT_EndGroup(Handle);
}
if(Window = LT_Layout(Handle,LocaleString(MSG_TERMBUFFER_ENTER_SEARCH_STRING_TXT),NULL,0,0,IDCMP_CLOSEWINDOW,0,
LAWN_HelpHook, &GuideHook,
WA_DepthGadget, TRUE,
WA_CloseGadget, TRUE,
WA_DragBar, TRUE,
WA_RMBTrap, TRUE,
WA_Activate, TRUE,
TAG_DONE))
{
struct IntuiMessage *Message;
BOOLEAN Done = FALSE;
ULONG MsgClass,
MsgQualifier;
UWORD MsgCode;
struct Gadget *MsgGadget;
ULONG SignalSet;
if(ParentTerminated)
ClrSignal(SIG_TOFRONT | SIG_KILL);
else
ClrSignal(SIG_BREAK);
LT_Activate(Handle,GAD_STRING);
do
{
if(ParentTerminated)
{
SignalSet = Wait(SIG_TOFRONT | SIG_KILL | PORTMASK(Window -> UserPort));
if(SignalSet & SIG_TOFRONT)
BumpWindow(Window);
if(SignalSet & SIG_KILL)
*ParentTerminated = Done = TRUE;
}
else
{
SignalSet = Wait(PORTMASK(Window -> UserPort) | SIG_BREAK);
if(SignalSet & SIG_BREAK)
Done = TRUE;
}
while(Message = (struct IntuiMessage *)GT_GetIMsg(Window -> UserPort))
{
MsgClass = Message -> Class;
MsgQualifier = Message -> Qualifier;
MsgCode = Message -> Code;
MsgGadget = (struct Gadget *)Message -> IAddress;
GT_ReplyIMsg(Message);
LT_HandleInput(Handle,MsgQualifier,&MsgClass,&MsgCode,&MsgGadget);
if(MsgClass == IDCMP_CLOSEWINDOW)
Done = TRUE;
if(MsgClass == IDCMP_GADGETUP)
{
switch(MsgGadget -> GadgetID)
{
case GAD_STRING:
if(MsgCode == '\r')
{
if(LocalBuffer[0])
{
strcpy(Buffer,LocalBuffer);
Success = TRUE;
LT_PressButton(Handle,GAD_OK);
}
else
LT_PressButton(Handle,GAD_CANCEL);
Done = TRUE;
}
break;
case GAD_OK:
if(LocalBuffer[0])
{
strcpy(Buffer,LocalBuffer);
Success = TRUE;
}
Done = TRUE;
break;
case GAD_CANCEL:
Done = TRUE;
break;
}
}
}
}
while(!Done);
}
LT_DeleteHandle(Handle);
}
return(Success);
}